package com.zhangmeng.tools.controller;

import cn.hutool.core.io.BufferUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.socket.aio.AioServer;
import cn.hutool.socket.aio.AioSession;
import cn.hutool.socket.aio.SimpleIoAction;
import cn.hutool.socket.nio.NioServer;
import com.zhangmeng.tools.utils.AlertUtils;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Date;

/**
 * @author : 芊芊墨客
 * @version : 1.0
 * @date : 2023-05-06 15:18
 */
@Slf4j
public class NioServerSocketController {

    @FXML
    public TextArea content;

    @FXML
    public TextField input;

    @FXML
    public Button send;

    @FXML
    public TextField port;

    public Button start_server;

    public Button close_server;

    private NioServer nioServer;

    private SocketChannel channel;

    private void appendMsg(String msg) {
        content.appendText(System.lineSeparator());
        content.appendText(msg);
    }

    @FXML
    public void initialize() {

        port.setText("8083");

        start_server.setOnAction(event -> {
            content.setText(null);
            if (port.getText().length() == 0) {
                AlertUtils.alert_warning("端口不能为空");
                return;
            }
            new Thread(() -> {
                nioServer = new NioServer(Integer.parseInt(port.getText()));
                nioServer.setChannelHandler((sc) -> {

                    channel = sc;

                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    try {
                        //从channel读数据到缓冲区
                        int readBytes = sc.read(readBuffer);
                        if (readBytes > 0) {
                            //Flips this buffer.  The limit is set to the current position and then
                            // the position is set to zero，就是表示要从起始位置开始读取数据
                            readBuffer.flip();
                            //eturns the number of elements between the current position and the  limit.
                            // 要读取的字节长度
                            byte[] bytes = new byte[readBuffer.remaining()];
                            //将缓冲区的数据读到bytes数组
                            readBuffer.get(bytes);
                            String body = StrUtil.utf8Str(bytes);
                            appendMsg("========>服务端接收"  + new Date()  + "=======>:" +  body);
                            //doWrite(sc, body);
                        } else if (readBytes < 0) {
                            IoUtil.close(sc);
                        }
                    } catch (IOException e) {
                        throw new IORuntimeException(e);
                    }
                });
                nioServer.listen();
            }).start();
        });

        send.setOnAction(event -> {
            send();
        });

        close_server.setOnAction(event -> {
           nioServer.close();
           appendMsg("服务关闭成功============================================================================================");
        });
    }

    public static void doWrite(SocketChannel channel, String msg) throws IOException {
        //将缓冲数据写入渠道，返回给客户端
        channel.write(BufferUtil.createUtf8(msg));
    }

    private void send() {
        if (input.getText().length() == 0) {
            AlertUtils.alert_warning("发送的内容不能为空");
            return;
        }
        String msg = input.getText();
        try {
            doWrite(channel,msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
        appendMsg("========>服务端发送" + new Date() + "=======>:" + msg);
    }
}
